package com.example.cms.Appointments;
import com.example.cms.DB.DBUtil;
import com.example.cms.Patients.Patient;
import com.example.cms.Patients.PatientsManager;
import com.example.cms.Queues.Queue;
import com.example.cms.Users.User;
import com.example.cms.Schedules.*;
import com.example.cms.Doctors.*;
import com.example.cms.Users.UsersManager;
import com.example.cms.Queues.*;
import java.sql.*;
import java.time.format.DateTimeFormatter;
import java.util.*;

public class AppointmentsManager {
    private Scanner scanner;
    private User currentUser;
    private SchedulesManager schedulesManager;
    private DoctorsManager doctorsManager;
    private PatientsManager patientsManager;
    private  AppointmentsManager appointmentsManager;
    private UsersManager usersManager;
    // 日期时间格式化器
    private DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
    public AppointmentsManager() {
        this.scanner = new Scanner(System.in);
    }
    // ==================== 预约管理 ====================
    public void showAppointmentMenu() {
        while (true) {
            System.out.println("\n--- 预约管理 ---");
            System.out.println("1. 创建预约");
            System.out.println("2. 查看预约");
            System.out.println("3. 取消预约");
            System.out.println("4. 查看我的预约");
            System.out.println("0. 返回主菜单");

            System.out.print("请选择操作: ");
            String choice = scanner.nextLine();

            switch (choice) {
                case "1":
                    createAppointment();
                    break;
                case "2":
                    viewAppointment();
                    break;
                case "3":
                    cancelAppointment();
                    break;
                case "4":
                    viewMyAppointments();
                    break;
                case "0":
                    return;
                default:
                    System.out.println("无效选择，请重新输入！");
            }
        }
    }

    private void createAppointment() {
        System.out.println("\n--- 创建预约 ---");
        try {
            System.out.print("患者ID: ");
            int patientId = Integer.parseInt(scanner.nextLine());

            System.out.print("排班ID: ");
            int scheduleId = Integer.parseInt(scanner.nextLine());

            System.out.print("症状描述: ");
            String symptoms = scanner.nextLine();

            Appointment appointment = new Appointment(patientId, scheduleId);
            appointment.setSymptoms(symptoms);
            // 获取排班信息设置费用
            Schedule schedule = schedulesManager.findScheduleById(scheduleId);
            if (schedule != null) {
                appointment.setFeeAmount(schedule.getFee());
            }
            if (addAppointment(appointment)) {
                System.out.println("预约创建成功！预约号: " + appointment.getAppointmentNo());
            } else {
                System.out.println("预约创建失败！");
            }
        } catch (Exception e) {
            System.out.println("创建失败: " + e.getMessage());
        }
    }
    private void viewAppointment() {
        System.out.println("\n--- 查看预约 ---");
        System.out.print("请输入预约ID: ");
        String input = scanner.nextLine();

        try {
            Appointment appointment = findAppointmentById(Integer.parseInt(input));

            if (appointment != null) {
                displayAppointmentInfo(appointment);
            } else {
                System.out.println("未找到预约信息！");
            }
        } catch (Exception e) {
            System.out.println("查询失败: " + e.getMessage());
        }
    }
    private void cancelAppointment() {
        System.out.println("\n--- 取消预约 ---");
        System.out.print("请输入预约ID: ");
        int appointmentId = Integer.parseInt(scanner.nextLine());

        try {
            if (cancelAppointmentById(appointmentId)) {
                System.out.println("预约取消成功！");
            } else {
                System.out.println("预约取消失败！");
            }
        } catch (Exception e) {
            System.out.println("取消失败: " + e.getMessage());
        }
    }
    private void viewMyAppointments() {
        System.out.println("\n--- 我的预约 ---");

        // 添加 null 检查
        if (currentUser == null) {
            System.out.println("用户未登录！");
            return;
        }

        try {
            List<Appointment> appointments;
            if (currentUser.isPatient()) {
                // 患者查看自己的预约
                Patient patient = patientsManager.findPatientByUserId(currentUser.getId());
                if (patient != null) {
                    appointments = getAppointmentsByPatientId(patient.getPatientId());
                } else {
                    System.out.println("未找到对应的患者信息！");
                    return;
                }
            } else if (currentUser.isDoctor()) {
                // 医生查看自己的预约
                Doctor doctor = doctorsManager.findDoctorByUserId(currentUser.getId());
                if (doctor != null) {
                    appointments = getAppointmentsByDoctorId(doctor.getDoctorId());
                } else {
                    System.out.println("未找到对应的医生信息！");
                    return;
                }
            } else {
                System.out.println("当前用户角色无法查看预约！");
                return;
            }

            if (appointments.isEmpty()) {
                System.out.println("暂无预约数据");
                return;
            }

            System.out.println("预约号\t患者\t医生\t时间\t状态\t费用");
            System.out.println("--------------------------------------------------------");
            for (Appointment appointment : appointments) {
                System.out.printf("%s\t%s\t%s\t%s\t%s\t%.2f\n",
                        appointment.getAppointmentNo(),
                        appointment.getPatientName(),
                        usersManager.getDoctorNameBySchedule(appointment.getScheduleId()),
                        appointment.getAppointmentTime().format(dateTimeFormatter),
                        appointment.getStatus(),
                        appointment.getFeeAmount());
            }
        } catch (Exception e) {
            System.out.println("获取预约列表失败: " + e.getMessage());
            e.printStackTrace(); // 添加详细错误信息
        }
    }
    private void displayAppointmentInfo(Appointment appointment) {
        System.out.println("\n=== 预约信息 ===");
        System.out.println("预约ID: " + appointment.getAppointmentId());
        System.out.println("预约号: " + appointment.getAppointmentNo());
        System.out.println("患者: " + appointment.getPatientName());
        System.out.println("患者电话: " + appointment.getPatientPhone());
        System.out.println("预约时间: " + appointment.getAppointmentTime());
        System.out.println("状态: " + appointment.getStatus());
        System.out.println("费用: " + appointment.getFeeAmount());
        System.out.println("支付状态: " + appointment.getPaymentStatus());
        System.out.println("症状: " + appointment.getSymptoms());
    }
    // 预约相关操作方法
    private boolean addAppointment(Appointment appointment) {
        String sql = "INSERT INTO appointments (patient_id, schedule_id, appointment_no, " +
                "appointment_time, status, fee_amount, symptoms) " +
                "VALUES (?, ?, ?, ?, ?, ?, ?)";
        try (Connection conn = DBUtil.getConnection();
             PreparedStatement pstmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) {
            pstmt.setInt(1, appointment.getPatientId());
            pstmt.setInt(2, appointment.getScheduleId());
            pstmt.setString(3, appointment.getAppointmentNo());
            pstmt.setTimestamp(4, Timestamp.valueOf(appointment.getAppointmentTime()));
            pstmt.setString(5, appointment.getStatus());
            pstmt.setDouble(6, appointment.getFeeAmount());
            pstmt.setString(7, appointment.getSymptoms());

            int affectedRows = pstmt.executeUpdate();
            if (affectedRows > 0) {
                try (ResultSet rs = pstmt.getGeneratedKeys()) {
                    if (rs.next()) {
                        appointment.setAppointmentId(rs.getInt(1));
                    }
                }
                // 更新排班的已预约数量
                updateBookedSlots(appointment.getScheduleId(), 1);
                return true;
            }
        } catch (SQLException e) {
            System.err.println("添加预约失败: " + e.getMessage());
        }
        return false;
    }

    public Appointment findAppointmentById(int appointmentId) {
        String sql = "SELECT a.*, p.name as patient_name, p.phone as patient_phone, " +
                "d.name as doctor_name, dept.dept_name, " +
                "s.schedule_date, s.time_slot, s.room_number " +
                "FROM appointments a " +
                "JOIN patients p ON a.patient_id = p.patient_id " +
                "JOIN schedules s ON a.schedule_id = s.schedule_id " +
                "JOIN doctors d ON s.doctor_id = d.doctor_id " +
                "JOIN departments dept ON d.department_id = dept.department_id " +
                "WHERE a.appointment_id = ?";

        try (   Connection conn = DBUtil.getConnection();
                PreparedStatement pstmt = conn.prepareStatement(sql)) {
            pstmt.setInt(1, appointmentId);
            try (ResultSet rs = pstmt.executeQuery()) {
                if (rs.next()) {
                    return mapResultSetToAppointment(rs);
                }
            }
        } catch (SQLException e) {
            System.err.println("查询预约失败: " + e.getMessage());
        }
        return null;
    }

    private boolean cancelAppointmentById(int appointmentId) {
        Connection conn = null;
        try {
            conn = DBUtil.getConnection();
            conn.setAutoCommit(false);

            // 获取预约信息
            Appointment appointment = findAppointmentById(appointmentId);
            if (appointment == null) {
                return false;
            }

            // 更新预约状态
            String updateAppointmentSQL = "UPDATE appointments SET status = 'CANCELLED' WHERE appointment_id = ?";
            try (PreparedStatement pstmt = conn.prepareStatement(updateAppointmentSQL)) {
                pstmt.setInt(1, appointmentId);
                pstmt.executeUpdate();
            }

            // 更新排班的已预约数量
            updateBookedSlots(appointment.getScheduleId(), -1);

            conn.commit();
            return true;
        } catch (SQLException e) {
            try {
                if (conn != null) conn.rollback();
            } catch (SQLException ex) {
                System.err.println("回滚失败: " + ex.getMessage());
            }
            System.err.println("取消预约失败: " + e.getMessage());
        } finally {
            try {
                if (conn != null) conn.setAutoCommit(true);
            } catch (SQLException e) {
                System.err.println("恢复自动提交失败: " + e.getMessage());
            }
        }
        return false;
    }

    private List<Appointment> getAppointmentsByPatientId(int patientId) {
        List<Appointment> appointments = new ArrayList<>();
        String sql = "SELECT a.*, p.name as patient_name, p.phone as patient_phone, " +
                "d.name as doctor_name, dept.dept_name, " +
                "s.schedule_date, s.time_slot, s.room_number " +
                "FROM appointments a " +
                "JOIN patients p ON a.patient_id = p.patient_id " +
                "JOIN schedules s ON a.schedule_id = s.schedule_id " +
                "JOIN doctors d ON s.doctor_id = d.doctor_id " +
                "JOIN departments dept ON d.department_id = dept.department_id " +
                "WHERE a.patient_id = ? ORDER BY a.appointment_time DESC";

        try (   Connection conn = DBUtil.getConnection();
                PreparedStatement pstmt = conn.prepareStatement(sql)) {
            pstmt.setInt(1, patientId);
            try (ResultSet rs = pstmt.executeQuery()) {
                while (rs.next()) {
                    appointments.add(mapResultSetToAppointment(rs));
                }
            }
        } catch (SQLException e) {
            System.err.println("获取患者预约失败: " + e.getMessage());
        }
        return appointments;
    }

    private List<Appointment> getAppointmentsByDoctorId(int doctorId) {
        List<Appointment> appointments = new ArrayList<>();
        String sql = "SELECT a.*, p.name as patient_name, p.phone as patient_phone, " +
                "d.name as doctor_name, dept.dept_name, " +
                "s.schedule_date, s.time_slot, s.room_number " +
                "FROM appointments a " +
                "JOIN patients p ON a.patient_id = p.patient_id " +
                "JOIN schedules s ON a.schedule_id = s.schedule_id " +
                "JOIN doctors d ON s.doctor_id = d.doctor_id " +
                "JOIN departments dept ON d.department_id = dept.department_id " +
                "WHERE s.doctor_id = ? AND a.status IN ('PENDING', 'CONFIRMED') " +
                "ORDER BY s.schedule_date, a.queue_number";

        try (   Connection conn = DBUtil.getConnection();
                PreparedStatement pstmt = conn.prepareStatement(sql)) {
            pstmt.setInt(1, doctorId);
            try (ResultSet rs = pstmt.executeQuery()) {
                while (rs.next()) {
                    appointments.add(mapResultSetToAppointment(rs));
                }
            }
        } catch (SQLException e) {
            System.err.println("获取医生预约失败: " + e.getMessage());
        }
        return appointments;
    }

    public boolean updateAppointmentStatus(int appointmentId, String status) {
        String sql = "UPDATE appointments SET status = ? WHERE appointment_id = ?";

        try (   Connection conn = DBUtil.getConnection();
                PreparedStatement pstmt = conn.prepareStatement(sql)) {
            pstmt.setString(1, status);
            pstmt.setInt(2, appointmentId);

            return pstmt.executeUpdate() > 0;
        } catch (SQLException e) {
            System.err.println("更新预约状态失败: " + e.getMessage());
        }
        return false;
    }


    private Appointment mapResultSetToAppointment(ResultSet rs) throws SQLException {
        Appointment appointment = new Appointment();
        Schedule schedule = new Schedule();
        Queue queue =new Queue() ;
        appointment.setAppointmentId(rs.getInt("appointment_id"));
        appointment.setPatientId(rs.getInt("patient_id"));
        appointment.setScheduleId(rs.getInt("schedule_id"));
        appointment.setAppointmentNo(rs.getString("appointment_no"));
        appointment.setAppointmentTime(rs.getTimestamp("appointment_time").toLocalDateTime());
        appointment.setQueueNumber(rs.getInt("queue_number"));
        appointment.setStatus(rs.getString("status"));
        appointment.setFeeAmount(rs.getDouble("fee_amount"));
        appointment.setPaidAmount(rs.getDouble("paid_amount"));
        appointment.setPaymentStatus(rs.getString("payment_status"));
        appointment.setSymptoms(rs.getString("symptoms"));
        // 额外信息
        appointment.setPatientName(rs.getString("patient_name"));
        appointment.setPatientPhone(rs.getString("patient_phone"));
        queue.setDoctorName(rs.getString("doctor_name"));
        queue.setDepartmentName(rs.getString("dept_name"));
        schedule.setScheduleDate(rs.getDate("schedule_date").toLocalDate());
        schedule.setTimeSlot(rs.getString("time_slot"));
        queue.setRoomNumber(rs.getString("room_number"));
        return appointment;
    }
    // 辅助方法
    private void updateBookedSlots(int scheduleId, int change) {
        String sql = "UPDATE schedules SET booked_slots = booked_slots + ? WHERE schedule_id = ?";

        try (   Connection conn = DBUtil.getConnection();
                PreparedStatement pstmt = conn.prepareStatement(sql)) {
            pstmt.setInt(1, change);
            pstmt.setInt(2, scheduleId);
            pstmt.executeUpdate();
        } catch (SQLException e) {
            System.err.println("更新排班预约数量失败: " + e.getMessage());
        }
    }
    public void setSchedulesManager(SchedulesManager schedulesManager) {
        this.schedulesManager = schedulesManager;
    }

    public void setPatientsManager(PatientsManager patientsManager) {
        this.patientsManager = patientsManager;
    }

    public void setDoctorsManager(DoctorsManager doctorsManager) {
        this.doctorsManager = doctorsManager;
    }

    public void setCurrentUser(User currentUser) {
        this.currentUser = currentUser;
    }

    public void setUsersManager(UsersManager usersManager) {
        this.usersManager = usersManager;
    }

}
